export default class Compile {
  constructor(el, vm) {
    this.vm = vm
    this.el = typeof el === 'string' ? document.querySelector(el) : el
    const fragments = this.node2Fragment(this.el)
    this.compile(fragments)
    this.el.appendChild(fragments)
  }
  node2Fragment(el) {
    const fragments = document.createDocumentFragment()
    let child
    while (child = el.firstChild) fragments.appendChild(child)
    return fragments
  }
  compile(el) {
    el.childNodes.forEach(node => {
      if (node.childNodes && node.childNodes.length) new Compile(node, this.vm)
      if (node.nodeType === 3 && /\{\{.+\}\}/.test(node.contentText)) {
        this.compileText(node, node.contentText)
      } else if (node.nodeType === 1) {
        this.compileElement(node)
      }
    })
  }
  compileText(node, content) {
    const key = content.match(/\{\{(.+)\}\}/)[1].trim()
    node.contentText = this.getVueValue(this.vm, key)
  }
  compileElement(node) {
    const attributes = [].slice.call(node.attributes)
    attributes.forEach(attr => {
      const name = attr.name
      const value = attr.value
      const method = name.split(':')[1]
      if (name.startsWith('v-')) {
        switch (name) {
          case 'v-html':
            node.innerHTML = this.getVueValue(this.vm, value)
            break
          case `v-on:${method}`:
            node[`on${method}`] = this.getVueValue(this.vm, value)
            break
        }
      }
    })
  }
  getVueValue(data, key) {
    let result = data
    const segments = key.split('.')
    segments.forEach(segment => {
      result = result[segment]
    })
    return result
  }
}
